package com.jdbc;


import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.*;

/**
 * ResultSetHandler 的实现
 * 将 ResultSet 的第一行转换为一个 JavaBean
 * 这个类是线程安全的
 */

public class BeanHandler<T> implements ResultSetHandler<T> {


    private Class<T> classType; //把结果集的一行数据封装成什么类型的对象
    public BeanHandler(Class<T> classType) {
        this.classType=classType;
    }
    public T handle(ResultSet rs) throws SQLException {
        //1)创建对应类的一个对象
        T obj= null;
        try {
            obj = classType.newInstance();
            //2)取出结果集中当前光标所在行的某一列数据
            BeanInfo beanInfo= null;
            beanInfo = Introspector.getBeanInfo(classType, Object.class);
            // 得到查询结果的元数据
            ResultSetMetaData data=rs.getMetaData();
            // 得到查询结果的列数
            int colCount = data.getColumnCount();
            if(rs.next()) {
                for(int i=1;i<=colCount;i++) {
                    try {
                        sqlType2JavaType(rs,data,obj,i);
                    }catch (Exception e1){
                        e1.printStackTrace();
                    }

                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }  catch (IntrospectionException e) {
            e.printStackTrace();
        }
        return obj;
    }


private void sqlType2JavaType(ResultSet rs,ResultSetMetaData data,T result,int i){
    // 获取结果集中的列名称
    String colName = null;
    try {
    colName = data.getColumnName(i);
    // 找到要封装成bean对象的属性
    Field field = null;
    field = findField(classType, colName);
    //获取属性的类型
    Class<?> fieldType = field.getType();
    //获取该属性的setter方法
    Method setMethod = findSetter(classType, getSetName(colName),
            fieldType);
    //根据属性类型从查询结果中根据列民获取该列的值，然后为该属性设置值
    if (fieldType == Boolean.class) {
        setMethod.invoke(result,
                Boolean.valueOf(rs.getBoolean(colName)));
    } else if (fieldType == Boolean.TYPE) {
        setMethod.invoke(result, rs.getBoolean(colName));
    } else if (fieldType == Byte.class) {
        setMethod.invoke(result,
                Byte.valueOf(rs.getByte(colName)));
    } else if (fieldType == Byte.TYPE) {
        setMethod.invoke(result, rs.getByte(colName));
    } else if (fieldType == Short.class) {
        setMethod.invoke(result,
                Short.valueOf(rs.getShort(colName)));
    } else if (fieldType == Short.TYPE) {
        setMethod.invoke(result, rs.getShort(colName));
    } else if (fieldType == Character.class) {
        setMethod.invoke(
                result,
                Character.valueOf(rs.getString(colName).charAt(
                        0)));
    } else if (fieldType == Character.TYPE) {
        setMethod.invoke(result, rs.getString(colName)
                .charAt(0));
    } else if (fieldType == Integer.class) {
        setMethod.invoke(result,
                Integer.valueOf(rs.getInt(colName)));
    } else if (fieldType == Integer.TYPE) {
        setMethod.invoke(result, rs.getInt(colName));
    } else if (fieldType == Long.class) {
        setMethod.invoke(result,
                Long.valueOf(rs.getLong(colName)));
    } else if (fieldType == Long.TYPE) {
        setMethod.invoke(result, rs.getLong(colName));
    } else if (fieldType == Float.class) {
        setMethod.invoke(result,
                Float.valueOf(rs.getFloat(colName)));
    } else if (fieldType == Float.TYPE) {
        setMethod.invoke(result, rs.getFloat(colName));
    } else if (fieldType == Double.class) {
        setMethod.invoke(result,
                Double.valueOf(rs.getDouble(colName)));
    } else if (fieldType == Double.TYPE) {
        setMethod.invoke(result, rs.getDouble(colName));
    } else if (fieldType == String.class) {
        setMethod.invoke(result, rs.getString(colName));
    } else if (fieldType == BigDecimal.class) {
        setMethod.invoke(result, rs.getBigDecimal(colName));
    } else {
        setMethod.invoke(result, rs.getObject(colName));
    }
} catch (SQLException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

    /**
     * 如果当前类没有该属性，则去父类上寻找是否有该属性，知道找到Object类，如果还是没有该属性，则返回空
     */
    public static Field findField(Class<?> clazz, String colName)
            throws Exception {
        try {
            return clazz.getDeclaredField(colName);
        } catch (NoSuchFieldException e) {
            Class<?> superClazz = clazz.getSuperclass();
            if (superClazz == null) {
                throw e;
            }
            return findField(superClazz, colName);
        }
    }

    private static Method findSetter(Class<?> clazz, String methodName,
                                     Class<?> paramType) throws NoSuchMethodException {
        try {
            return clazz.getDeclaredMethod(methodName,
                    new Class<?>[] { paramType });
        } catch (NoSuchMethodException e) {
            Class<?> superClazz = clazz.getSuperclass();
            if (superClazz == null) {
                throw e;
            }
            return findSetter(superClazz, methodName, paramType);
        }
    }


    //拼Set方法
    private static String getSetName(String colName) {
        if (colName.length() == 1) {
            return "set" + Character.toUpperCase(colName.charAt(0));
        } else {
            return "set" + Character.toUpperCase(colName.charAt(0))
                    + colName.substring(1);
        }
    }

}
